﻿namespace Frameworks
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;

    public static class AssemblyUtility
    {
        public static Assembly[] AppAssemblies { get; private set; }
        public static Assembly ExecutingAssemblie { get; private set; }
        public static Dictionary<string, Type> CachedTypes { get; private set; }

        static AssemblyUtility()
        {
            AppAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            ExecutingAssemblie = Assembly.GetExecutingAssembly();
            CachedTypes = new Dictionary<string, Type>();
        }

        /// <summary>
        /// 获取已加载的程序集中的所有类型
        /// </summary>
        /// <returns></returns>
        public static Type[] GetTypes()
        {
            try
            {
                List<Type> allTypes = new List<Type>();
                for (int i = 0; i < AppAssemblies.Length; i++)
                {
                    allTypes.AddRange(AppAssemblies[i].GetTypes());
                }

                return allTypes.ToArray();
            }
            catch (Exception ex) { throw ex; }
        }

        public static Type[] GetTypes(string[] assemblyFullName)
        {
            try
            {
                if (assemblyFullName == null)
                    throw new ArgumentNullException("assemblyFullName is invalid");

                Type[] types = null;
                for (int i = 0; i < AppAssemblies.Length; i++)
                {
                    for (int j = 0; j < assemblyFullName.Length; j++)
                    {
                        if (AppAssemblies[i].FullName == assemblyFullName[j])
                        {
                            types = types.Concat(AppAssemblies[i].GetExportedTypes()).ToArray();
                        }
                    }
                }
                return types;
            }
            catch (Exception ex) { throw ex; }
        }

        /// <summary>
        /// 获取已加载的程序集中的指定类型
        /// </summary>
        /// <param name="typeName">类型名</param>
        /// <returns></returns>
        public static Type GetType(string typeName)
        {
            try
            {
                if (string.IsNullOrEmpty(typeName))
                    throw new ArgumentNullException("typeName is invalid");

                Type type = null;
                if (CachedTypes.TryGetValue(typeName, out type))
                    return type;

                type = Type.GetType(typeName);
                if (type != null)
                {
                    CachedTypes.Add(typeName, type);
                    return type;
                }

                foreach (Assembly assembly in AppAssemblies)
                {
                    type = Type.GetType(string.Format("{0}, {1}", typeName, assembly.FullName));

                    if (type != null)
                    {
                        CachedTypes.Add(typeName, type);
                        return type;
                    }
                }

                return null;
            }
            catch (Exception ex) { throw ex; }
        }
    }
}
